//********************************************************************
// 
//  file:  UploadStream.cs
//  Stream Upload Implementation to allow progress during upload
//
//  (C) Copyright 2010, Diomede Corporation
//  All rights reserved
// 
//  Use, modification, and distribution is subject to   
//  the New BSD License (See accompanying file license.txt).
// 
//********************************************************************

using System;
using System.IO;

namespace Diomede.SDK
{
    /// <summary>
    /// A Stream implementation to allow progress report during uploading.
    /// </summary>
    public class UploadStream : Stream
    {
        private readonly Stream stream;
        private readonly long length;
        private long bytesRead;

        /// <summary>
        /// Event for progress changed.
        /// </summary>
        public event EventHandler<FileUploadProgressArgs> ProgressChanged;

        /// <summary>
        /// UploadStream constructor that will accept the original FileStream
        /// </summary>
        /// <param name="file">File stream to upload</param>
        public UploadStream(FileStream file)
        {
            this.stream = file;
            length = file.Length;
            bytesRead = 0;
            if (ProgressChanged != null) ProgressChanged(this, new FileUploadProgressArgs(bytesRead, length));

        }

        public UploadStream(MemoryStream mem)
        {
            this.stream = mem;
            length = mem.Length;
            bytesRead = 0;
            if (ProgressChanged != null) ProgressChanged(this, new FileUploadProgressArgs(bytesRead, length));
        }

        /// <summary>
        /// CanRead implementation
        /// </summary>
        public override bool CanRead
        {
            get { return true; }
        }

        /// <summary>
        /// CanSeek implementation, see <see cref="FileStream.CanSeek"/> for more information
        /// </summary>
        public override bool CanSeek
        {
            get { return false; }
        }

        /// <summary>
        /// CanWrite implementation, see <see cref="FileStream.CanWrite"/> for more information
        /// </summary>
        public override bool CanWrite
        {
            get { return false; }
        }

        /// <summary>
        /// Flush implementation, see <see cref="FileStream.Flush"/> for more information
        /// </summary>
        public override void Flush()
        {
        }

        /// <summary>
        /// Length implementation, see <see cref="FileStream.Length"/> for more information
        /// </summary>
        public override long Length
        {
            get { return length; }
        }

        /// <summary>
        /// Position implementation, see <see cref="FileStream.Position"/> for more information
        /// </summary>
        public override long Position
        {
            get
            {
                return bytesRead;
            }
            set
            {
                throw new Exception("The method or operation is not implemented.");
            }
        }

        /// <summary>
        /// Read implementation, see <see cref="FileStream.Read"/> for more information
        /// </summary>
        /// <param name="buffer">Read buffer</param>
        /// <param name="offset">Offset</param>
        /// <param name="count">Count</param>
        /// <returns>Length of read data.</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            int result = stream.Read(buffer, offset, count);
            bytesRead += result;
            if (ProgressChanged != null) ProgressChanged(this, new FileUploadProgressArgs(bytesRead, length));
            return result;
        }

        /// <summary>
        /// Seek implementation, see <see cref="FileStream.Seek"/> for more information
        /// </summary>
        /// <param name="offset">Offset</param>
        /// <param name="origin">Origin</param>
        /// <returns></returns>
        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        /// <summary>
        /// SetLength override
        /// </summary>
        /// <param name="value">value</param>
        public override void SetLength(long value)
        {
            throw new Exception("The method or operation is not implemented.");
        }
        /// <summary>
        /// Write implementation, see <see cref="FileStream.Write"/> for more information
        /// </summary>
        /// <param name="buffer">buffer</param>
        /// <param name="offset">offset</param>
        /// <param name="count">count</param>
        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new Exception("The method or operation is not implemented.");
        }
    }
}